package org.penguin.study.bk.elasticsearch.service;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.penguin.study.bk.elasticsearch.entity.Product;
import org.penguin.study.bk.elasticsearch.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author chengyinghua
 */
@Slf4j
@Service
@ConditionalOnProperty(name = "elasticsearch.enable", havingValue = "true")
public class ProductService {

    private static final String PRODUCT_INDEX = "productindex";

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    public void createProductIndexBulk(final List<Product> products) {
        productRepository.saveAll(products);
    }

    public void createProductIndex(final Product product) {
        IndexQuery indexQuery = new IndexQueryBuilder()
                .withId(product.getId())
                .withObject(product).build();

        String documentId = elasticsearchOperations
                .index(indexQuery, IndexCoordinates.of(PRODUCT_INDEX));

        productRepository.save(product);
        log.debug("Elasticsearch createProductIndex-> " + documentId + " <> " + product.getId());
    }

    public Iterable<Product> getAll() {
        return productRepository.findAll();
    }

    public List<SearchHit<Product>> findProductsByManufacturer(final String manufacturer) {
        QueryBuilder queryBuilder =
                QueryBuilders
                        .matchQuery("manufacturer", manufacturer);

        Query searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .build();

        SearchHits<Product> productHits =
                elasticsearchOperations
                        .search(searchQuery,
                                Product.class,
                                IndexCoordinates.of(PRODUCT_INDEX));
        log.debug("Elasticsearch findProductsByManufacturer-> " + productHits);
        return productHits.getSearchHits();
    }

    public void findByProductPrice(final double min, double max) {
        Criteria criteria = new Criteria("price")
                .greaterThan(min)
                .lessThan(max);

        Query searchQuery = new CriteriaQuery(criteria);

        SearchHits<Product> products = elasticsearchOperations
                .search(searchQuery,
                        Product.class,
                        IndexCoordinates.of(PRODUCT_INDEX));
        log.debug("Elasticsearch findByProductPrice-> " + products);

    }

    public List<Product> findByName(String name) {
        return productRepository.findByName(name);
    }
}
